const http = require('http');
const https = require('https');
const httpProxy = require('http-proxy');
const fs = require('fs');
const path = require('path');
const url = require('url');

// 配置参数
const CONFIG = {
  // HTTP 代理服务器端口
  httpPort: process.env.HTTP_PORT || 8080,
  // HTTPS 代理服务器端口
  httpsPort: process.env.HTTPS_PORT || 8443,
  // 日志文件路径
  logFile: process.env.LOG_FILE || path.join(__dirname, 'proxy.log'),
  // 是否启用 HTTPS 代理
  enableHttps: process.env.ENABLE_HTTPS === 'true' || false,
};

// 日志记录函数
function log(level, message) {
  const timestamp = new Date().toISOString();
  const logMessage = `[${timestamp}] [${level}] ${message}`;
  
  console.log(logMessage);
  
  // 写入日志文件
  try {
    fs.appendFileSync(CONFIG.logFile, logMessage + '\n');
  } catch (err) {
    console.error('无法写入日志文件:', err.message);
  }
}

// 创建代理实例
const proxy = httpProxy.createProxyServer({
  // 保留原始主机头
  changeOrigin: true,
  // 保留原始路径
  prependPath: true,
  // 超时时间（毫秒）
  timeout: 30000,
  // 代理超时时间
  proxyTimeout: 30000,
  // 跟随重定向
  followRedirects: true,
});

// 代理错误处理
proxy.on('error', (err, req, res) => {
  log('ERROR', `代理请求失败: ${err.message}`);
  
  if (!res.headersSent) {
    res.writeHead(502, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({
      error: '网关错误',
      message: '无法连接到目标服务器',
      details: err.message,
    }));
  }
});

// 代理响应事件
proxy.on('proxyRes', (proxyRes, req) => {
  log('INFO', `${req.method} ${req.url} -> ${proxyRes.statusCode}`);
});

// 存储会话中的目标 URL（用于相对路径请求）
const sessionTargets = new Map();

// 获取目标 URL 的多种方式
function getTargetUrl(req) {
  // 方式 1：请求头中的 X-Proxy-Target
  if (req.headers['x-proxy-target']) {
    return req.headers['x-proxy-target'];
  }
  
  // 方式 2：查询参数中的 target
  const parsedUrl = url.parse(req.url, true);
  if (parsedUrl.query.target) {
    return parsedUrl.query.target;
  }
  
  // 方式 3：路径前缀模式 /proxy/http://example.com/path
  if (req.url.startsWith('/proxy/')) {
    const targetPart = req.url.substring(7); // 移除 '/proxy/' 前缀
    if (targetPart.startsWith('http://') || targetPart.startsWith('https://')) {
      return targetPart;
    }
  }
  
  return null;
}

// 处理相对路径请求
function resolveRelativePath(req, baseTargetUrl) {
  try {
    const requestPath = req.url.split('?')[0]; // 移除查询参数
    const resolvedUrl = new URL(requestPath, baseTargetUrl).toString();
    return resolvedUrl;
  } catch (err) {
    log('ERROR', `解析相对路径失败: ${err.message}`);
    return null;
  }
}

// 创建 HTTP 代理服务器
function createHttpServer() {
  const server = http.createServer((req, res) => {
    const clientIp = req.socket.remoteAddress;
    
    log('INFO', `收到 HTTP 请求: ${req.method} ${req.url} 来自 ${clientIp}`);
    
    try {
      // 尝试从请求中获取目标 URL
      let targetUrl = getTargetUrl(req);
      
      // 如果没有找到目标 URL，尝试从会话中获取
      if (!targetUrl && sessionTargets.has(clientIp)) {
        const baseTarget = sessionTargets.get(clientIp);
        targetUrl = resolveRelativePath(req, baseTarget);
      }
      
      if (!targetUrl) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({
          error: '请求错误',
          message: '未指定目标 URL。使用 ?target=http://example.com 或设置 X-Proxy-Target 请求头',
        }));
        return;
      }
      
      // 保存基础 URL 到会话（用于后续的相对路径请求）
      // 只在有新的目标 URL 时才保存
      if (targetUrl && !targetUrl.includes('://')) {
        // 这是一个相对路径，不需要保存
      } else if (targetUrl) {
        // 提取基础 URL（不包含路径）
        try {
          const urlObj = new URL(targetUrl);
          const baseUrlStr = `${urlObj.protocol}//${urlObj.host}`;
          sessionTargets.set(clientIp, baseUrlStr);
        } catch (err) {
          // 如果无法解析，保存整个 URL
          sessionTargets.set(clientIp, targetUrl);
        }
      }
      
      // 转发请求到目标服务器
      proxy.web(req, res, { target: targetUrl });
    } catch (err) {
      log('ERROR', `处理 HTTP 请求时出错: ${err.message}`);
      res.writeHead(500, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({
        error: '服务器错误',
        message: err.message,
      }));
    }
  });
  
  return server;
}

// 创建 HTTPS 代理服务器
function createHttpsServer() {
  // 检查 SSL 证书文件
  const certPath = process.env.CERT_PATH || path.join(__dirname, 'cert.pem');
  const keyPath = process.env.KEY_PATH || path.join(__dirname, 'key.pem');
  
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
    log('WARN', 'HTTPS 证书文件不存在，跳过 HTTPS 服务器创建');
    return null;
  }
  
  try {
    const options = {
      cert: fs.readFileSync(certPath),
      key: fs.readFileSync(keyPath),
    };
    
    const server = https.createServer(options, (req, res) => {
      const clientIp = req.socket.remoteAddress;
      
      log('INFO', `收到 HTTPS 请求: ${req.method} ${req.url} 来自 ${clientIp}`);
      
      try {
        // 尝试从请求中获取目标 URL
        let targetUrl = getTargetUrl(req);
        
        // 如果没有找到目标 URL，尝试从会话中获取
        if (!targetUrl && sessionTargets.has(clientIp)) {
          const baseTarget = sessionTargets.get(clientIp);
          targetUrl = resolveRelativePath(req, baseTarget);
        }
        
        if (!targetUrl) {
          res.writeHead(400, { 'Content-Type': 'application/json' });
          res.end(JSON.stringify({
            error: '请求错误',
            message: '未指定目标 URL',
          }));
          return;
        }
        
        // 保存目标 URL 到会话
        const baseUrl = getTargetUrl(req);
        if (baseUrl) {
          sessionTargets.set(clientIp, baseUrl);
        }
        
        // 转发请求到目标服务器
        proxy.web(req, res, { target: targetUrl });
      } catch (err) {
        log('ERROR', `处理 HTTPS 请求时出错: ${err.message}`);
        res.writeHead(500, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({
          error: '服务器错误',
          message: err.message,
        }));
      }
    });
    
    return server;
  } catch (err) {
    log('ERROR', `创建 HTTPS 服务器失败: ${err.message}`);
    return null;
  }
}

// 启动服务器
function startServers() {
  // 启动 HTTP 代理服务器
  const httpServer = createHttpServer();
  httpServer.listen(CONFIG.httpPort, () => {
    log('INFO', `HTTP 代理服务器已启动，监听端口 ${CONFIG.httpPort}`);
  });
  
  // 启动 HTTPS 代理服务器（如果启用）
  if (CONFIG.enableHttps) {
    const httpsServer = createHttpsServer();
    if (httpsServer) {
      httpsServer.listen(CONFIG.httpsPort, () => {
        log('INFO', `HTTPS 代理服务器已启动，监听端口 ${CONFIG.httpsPort}`);
      });
    }
  }
  
  // 处理进程信号
  process.on('SIGINT', () => {
    log('INFO', '收到 SIGINT 信号，正在关闭服务器...');
    httpServer.close(() => {
      log('INFO', 'HTTP 代理服务器已关闭');
      process.exit(0);
    });
  });
  
  process.on('SIGTERM', () => {
    log('INFO', '收到 SIGTERM 信号，正在关闭服务器...');
    httpServer.close(() => {
      log('INFO', 'HTTP 代理服务器已关闭');
      process.exit(0);
    });
  });
}

// 启动应用
log('INFO', '正在启动代理服务器...');
startServers();

